home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Language/OS - Multiplatform Resource Library
/
LANGUAGE OS.iso
/
oper_sys
/
emerald
/
emrldsys.lha
/
Language
/
Compiler
/
emit.c
< prev
next >
Wrap
C/C++ Source or Header
|
1990-08-16
|
9KB
|
392 lines
/*
* @(#)emit.c 1.6 1/20/89
*/
#include "assert.h"
#include "genutils.h"
#include "nodes.h"
#include "builtins.h"
#include "regdefs.h"
#include "flags.h"
#include "trace.h"
#include "consts.h"
#include "sequence.h"
Boolean doGenerateCode = 1;
/*VARARGS1*/
void emit(format, args)
char *format;
int args;
{
if (doGenerateCode) _doprnt(format, &args, codeFile);
IFTRACE(emit, 1) _doprnt(format, &args, stdout);
}
Boolean isPush(d)
DD d;
{
if (d.kind != DD_Address) return(FALSE);
if (d.value.address.base != regs_sp) return(FALSE);
return (d.value.address.autoDecrement);
}
Boolean isMemory(d)
DD d;
{
if (d.kind != DD_Address) return(FALSE);
return(d.value.address.base != Register);
}
Boolean isAddressRegister(d)
DD d;
{
#ifdef sun
static int addressRegs = 0xf033;
#endif
#ifdef vax
static int addressRegs = 0xffff;
#endif
if (d.kind != DD_Address) return(FALSE);
if (d.value.address.base != Register) return(FALSE);
return(addressRegs & (1 << d.value.address.offset));
}
Boolean isDataRegister(d)
DD d;
{
#ifdef sun
static int dataRegs = 0x0fcc;
#endif
#ifdef vax
static int dataRegs = 0xffff;
#endif
if (d.kind != DD_Address) return(FALSE);
if (d.value.address.base != Register) return(FALSE);
return(dataRegs & (1 << d.value.address.offset));
}
Boolean isRegisterDD(d)
DD d;
{
if (d.kind != DD_Address) return(FALSE);
return(d.value.address.base == Register);
}
Boolean isAppropriateRegister(d, brand)
DD d;
Brand brand;
{
return ((brand == DataBrand && isDataRegister(d)) ||
(brand == ODPBrand && isAddressRegister(d)));
}
Boolean isManifestDD(d)
DD d;
{
return(d.kind == DD_Manifest || d.kind == DD_RealManifest);
}
static void outDD(d, c)
DD d;
char c;
{
writeDD(d, c);
IFTRACE(emitmove, 1) displayDD(stdout, d, c);
}
/*VARARGS1*/
static void out0(s)
char *s;
{
emit(s);
TRACE0(emitmove, 1, s);
}
/*VARARGS1*/
static void out1(s, x)
char *s;
int x;
{
emit(s, x);
TRACE1(emitmove, 1, s, x);
}
/*VARARGS1*/
static void out2(s, x, y)
char *s;
int x, y;
{
emit(s, x, y);
TRACE2(emitmove, 1, s, x, y);
}
/*VARARGS1*/
static void out3(s, x, y, z)
char *s;
int x, y, z;
{
emit(s, x, y, z);
TRACE3(emitmove, 1, s, x, y, z);
}
void emitMoveAddress(from, to)
DD from, to;
{
assert(!DDNeedsLabel(from));
assert(from.kind == DD_Address);
#ifdef vax
out0("\tmoval\t");
#endif
#ifdef sun
out0("\tlea\t");
#endif
outDD(from, ',');
outDD(to, '\n');
wroteCode = TRUE;
}
void emitMove(from, to, size)
DD from, to;
char size;
{
int trueLabel, endLabel;
DD intermediate;
if (isSameDD(from, to)) return;
assert(to.kind == DD_Address);
if (DDNeedsLabel(from)) {
currentInstruction = nextLabelNumber++;
out1("L_%d:\t", currentInstruction);
} else {
out0("\t");
}
if (from.kind == DD_PSLCondition) {
#ifdef vax
if (FALSE) {
#endif
#ifdef sun
if (isDataRegister(to) && size == 'l') {
emit("%ss%s\t", JF(from.value.condition.isFloat),
JN(from.value.condition.psl));
writeDD(to, '\n');
emit("\textbl\t");
writeDD(to, '\n');
emit("\tnegl\t");
writeDD(to, '\n');
#endif
} else {
trueLabel = nextLabelNumber++;
endLabel = nextLabelNumber++;
out3("%sb%s\tL_%d\n", JF(from.value.condition.isFloat),
JN(from.value.condition.psl), trueLabel);
intermediate.kind = DD_Manifest;
intermediate.value.manifest = 0;
emitMove(intermediate, to, size);
out2("\tj%s\tL_%d\n", JN(ALWAYS), endLabel);
out1("L_%d:\n", trueLabel);
intermediate.value.manifest = 1;
emitMove(intermediate, to, size);
out1("L_%d:\n", endLabel);
}
} else if (from.kind == DD_Self) {
assert(size == 'l');
trueLabel = nextLabelNumber++;
endLabel = nextLabelNumber++;
emitBranchOnBit(ODTag_global, 's', regs_g, buildLabelDD(trueLabel));
intermediate = buildRegisterDD(regs_g);
emitMove(intermediate, to, size);
emit("\tj%s\tL_%d\n", JN(ALWAYS), endLabel);
emit("L_%d:\n", trueLabel);
intermediate = buildRegisterDD(regs_b);
emitMove(intermediate, to, size);
emit("L_%d:\n", endLabel);
#ifdef vax
} else if (from.kind == DD_Manifest && from.value.manifest == 0) {
#endif
#ifdef sun
} else if (from.kind == DD_Manifest && from.value.manifest == 0 &&
!isAddressRegister(to)) {
#endif
out1("clr%c\t", size);
outDD(to, '\n');
#ifdef vax
} else if (size == 'l' && isPush(to) && from.kind != DD_RealManifest) {
if (from.kind == DD_Label) {
/* use pushal */
out0("pushal\t");
outDD(from, '\n');
} else {
/* use pushl */
out0("pushl\t");
outDD(from, '\n');
}
#endif
#ifdef sun
} else if (size == 'l' && isPush(to) && from.kind == DD_Label) {
/* use pea */
out0("pea\t");
outDD(from, '\n');
#endif
} else if (from.kind == DD_RealManifest) {
assert(size == 'l' || size == 'f');
#ifdef vax
out1("movf\t");
#endif
#ifdef sun
out1("movl\t");
#endif
outDD(from, ',');
outDD(to, '\n');
} else if (from.kind == DD_Label) {
#ifdef vax
out1("moval\t");
outDD(from, ',');
outDD(to, '\n');
#endif
#ifdef sun
if (isAddressRegister(to)) {
out0("lea\t");
outDD(from, ',');
outDD(to, '\n');
} else {
out0("pea\t");
outDD(from,'\n');
out0("\tmovl\t");
outDD(popper, ',');
outDD(to, '\n');
}
#endif
} else {
#ifdef sun
if (from.kind == DD_Manifest && isDataRegister(to) &&
inRange(from.value.manifest, -128, 127) && size == 'l') {
out1("moveq\t");
} else {
out1("mov%c\t", size);
}
#endif
#ifdef vax
out1("mov%c\t", size);
#endif
outDD(from, ',');
outDD(to, '\n');
}
wroteCode = TRUE;
}
/*VARARGS1*/
void Comment(format, args)
char *format;
int args;
{
if (doGenerateCode) {
fprintf(codeFile, " %c ", COMMENTCHAR);
_doprnt(format, &args, codeFile);
(void) fputc('\n', codeFile);
}
IFTRACE(emit, 1) {
fprintf(stdout, " %c ", COMMENTCHAR);
_doprnt(format, &args, stdout);
(void) fputc('\n', stdout);
}
}
writeStringData(s)
char *s;
{
int extra;
extra = 4 - (strlen(s) % 4);
if (extra == 4) extra = 0;
emit("\t.ascii\t\""); /* data */
for (; *s; s++) {
if (*s == '"') {
emit("\\\"");
} else if (*s == '\\') {
emit("\\\\");
} else if (*s >= ' ' && *s <= '~') {
emit("%c",*s);
} else {
emit("\\%03o", *s);
}
}
for (; extra; extra--) {
emit("\\000");
}
emit("\"\n");
}
void emitStringObject(s, labelNumber, extraString, extraNumber)
register char *s;
int labelNumber;
char *extraString;
int extraNumber;
{
ODTag tag;
tag = BuildTag(LOTag, TRUE);
tag.gcDoNotCollect = TRUE;
/* write the codeoid here to facilitate garbage collection */
writeHexComment(currentCodeOID, "Code OID containing this String");
if (extraString != NULL) emit("L_%s:\n", extraString);
emit("L_%d:", labelNumber);
writeTag(tag); /* tag */
writeHex((unsigned)0xabcdef01); /* codePtr */
saveRelocationInfo(labelNumber, 4, AR_OIDToCodePtr,
OIDOfBuiltin(B_INSTCT, STRINGINDEX), 0);
writeData(0); /* ownOID */
writeData(strlen(s)); /* sizeInBytes */
writeStringData(s);
}
void emitVectorObject(vector, labelNumber, elementTypeSize, vecCodeOID)
NodePtr vector;
int labelNumber, elementTypeSize;
OID vecCodeOID;
{
ODTag tag;
int nElements, extra;
Variable v;
char *labelname;
NodePtr p;
tag = BuildTag(LOTag, TRUE);
tag.gcDoNotCollect = TRUE;
/* write the codeoid here to facilitate garbage collection */
writeHexComment(currentCodeOID, "Code OID containing this Vector");
emit("L_%d:", labelNumber);
writeTag(tag); /* tag */
writeHex((unsigned)0xabcdef01); /* codePtr */
saveRelocationInfo(labelNumber, 4, AR_OIDToCodePtr, vecCodeOID, 0);
writeData(0); /* ownOID */
nElements = Sequence_Length(vector->b.vectorlit.exp);
writeData(nElements - 1); /* upb */
writeData(nElements * elementTypeSize); /* sizeInBytes */
extra = 4 - ((nElements * elementTypeSize) % 4);
if (extra == 4) extra = 0;
labelname = elementTypeSize == 1 ? ".byte" : ".long";
Sequence_For(p, vector->b.vectorlit.exp)
vPushValue(p, pusherContext);
v = vPop();
switch (v.data.kind) {
case DD_Manifest:
emit("\t%s\t%d\n", labelname, v.data.value.manifest);
break;
case DD_Label:
emit("\t%s\tL_%d\n", labelname, v.data.value.label);
break;
default:
assert(FALSE);
break;
}
if (elementTypeSize == 8) {
writeHex((unsigned)0xabcdef01); /* codePtr */
saveRelocationInfo(labelNumber, IMVector_data + (z__z * 8) + 4,
AR_OIDOIDToAbCon, getDDAbstractType(v.abCon),
getDDConcreteType(v.abCon));
}
Sequence_Next
for (; extra; extra--) {
emit("\t%s\t0\n", labelname);
}
}